package com.lhj.xxsc.ware.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.xxsc.common.exception.NoStockExceptoin;
import com.xxsc.common.to.mq.OrderTo;
import com.xxsc.common.to.mq.StockDetailTo;
import com.xxsc.common.to.mq.StockLockedTo;
import com.xxsc.common.utils.R;
import com.lhj.xxsc.ware.entity.WareOrderTaskDetailEntity;
import com.lhj.xxsc.ware.entity.WareOrderTaskEntity;
import com.lhj.xxsc.ware.feign.OrderFeignService;
import com.lhj.xxsc.ware.feign.ProductFeignService;
import com.lhj.xxsc.ware.service.WareOrderTaskDetailService;
import com.lhj.xxsc.ware.service.WareOrderTaskService;
import com.lhj.xxsc.ware.vo.*;
import lombok.Data;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xxsc.common.utils.PageUtils;
import com.xxsc.common.utils.Query;

import com.lhj.xxsc.ware.dao.WareSkuDao;
import com.lhj.xxsc.ware.entity.WareSkuEntity;
import com.lhj.xxsc.ware.service.WareSkuService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;


@Service("wareSkuService")
public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> implements WareSkuService {

	@Autowired
	WareSkuDao wareSkuDao;
	@Autowired
	RabbitTemplate rabbitTemplate;
	@Autowired
	ProductFeignService productFeignService;
	@Autowired
	WareOrderTaskService wareOrderTaskService;
	@Autowired
	WareOrderTaskDetailService wareOrderTaskDetailService;
	@Autowired
	OrderFeignService orderFeignService;

	@Override
	public PageUtils queryPage(Map<String, Object> params) {
		/**
		 * skuId: 1
		 * wareId: 2
		 */
		QueryWrapper<WareSkuEntity> queryWrapper = new QueryWrapper<>();
		String skuId = (String) params.get("skuId");
		if (!StringUtils.isEmpty(skuId)) {
			queryWrapper.eq("sku_id", skuId);
		}

		String wareId = (String) params.get("wareId");
		if (!StringUtils.isEmpty(wareId)) {
			queryWrapper.eq("ware_id", wareId);
		}


		IPage<WareSkuEntity> page = this.page(
				new Query<WareSkuEntity>().getPage(params),
				queryWrapper
		);

		return new PageUtils(page);
	}

	@Override
	public void addStock(Long skuId, Long wareId, Integer skuNum) {
		//1、判断如果还没有这个库存记录新增
		List<WareSkuEntity> entities = wareSkuDao.selectList(new QueryWrapper<WareSkuEntity>().eq("sku_id", skuId).eq("ware_id", wareId));
		if (entities == null || entities.size() == 0) {
			WareSkuEntity skuEntity = new WareSkuEntity();
			skuEntity.setSkuId(skuId);
			skuEntity.setStock(skuNum);
			skuEntity.setWareId(wareId);
			skuEntity.setStockLocked(0);
			//TODO 远程查询sku的名字，如果失败，整个事务无需回滚
			//1、自己catch异常
			//TODO 还可以用什么办法让异常出现以后不回滚？高级
			try {
				R info = productFeignService.info(skuId);
				Map<String, Object> data = (Map<String, Object>) info.get("skuInfo");

				if (info.getCode() == 0) {
					skuEntity.setSkuName((String) data.get("skuName"));
				}
			} catch (Exception e) {

			}


			wareSkuDao.insert(skuEntity);
		} else {
			wareSkuDao.addStock(skuId, wareId, skuNum);
		}

	}

	@Override
	public List<SkuHasStockVo> getSkusHasStock(List<Long> skuIds) {
		List<SkuHasStockVo> collect = skuIds.stream().map(
				skuId -> {
					SkuHasStockVo vo = new SkuHasStockVo();

					// 查询当前sku的总库存量
					Long count = baseMapper.getSkuStock(skuId);
					vo.setSkuId(skuId);
					vo.setHasStock(count == null ? false : count > 0);
					return vo;
				}).collect(Collectors.toList());

		return collect;
	}

	/**
	 * 解锁场景：
	 * 下单解锁：订单过期后没有支付自动取消，手动取消，解锁
	 * 下单成功，接下来的业务调用失败，导致订单回滚。要自动解锁。
	 *
	 * @param vo
	 * @return
	 */
	@Override
	@Transactional
	public Boolean orderLockStock(WareSkuLockVo vo) {
		// 保存工作单内容，为了后面回滚查询
		WareOrderTaskEntity taskEntity = new WareOrderTaskEntity();
		taskEntity.setOrderSn(vo.getOrderSn());
		wareOrderTaskService.save(taskEntity);

		// 找到每个商品在哪个仓库有库存
		List<OrderItemVo> locks = vo.getLocks();
		List<SkuWareHasStock> collect = locks.stream().map(item -> {
			SkuWareHasStock skuWareHasStock = new SkuWareHasStock();
			Long skuId = item.getSkuId();
			skuWareHasStock.setSkuId(skuId);
			skuWareHasStock.setNum(item.getCount());
			//查询库存
			List<Long> wareIds = wareSkuDao.listWareIdHasSkuStock(skuId);
			skuWareHasStock.setWareId(wareIds);
			return skuWareHasStock;
		}).collect(Collectors.toList());

		for (SkuWareHasStock hasStock : collect) {
			Boolean skuStocked = false;
			Long skuId = hasStock.getSkuId();
			List<Long> wareIds = hasStock.getWareId();
			if (CollectionUtils.isEmpty(wareIds)) {
				// 直接锁库失败
				throw new NoStockExceptoin(skuId);
			}
			// 如果有一个仓库锁定成功了，就可以将当前商品锁定
			for (Long wareId : wareIds) {
				// 成功则返回 1 否则则返回 0
				Long count = wareSkuDao.lcokSkuStock(skuId, wareId, hasStock.getNum());
				if (count == 1) {
					skuStocked = true;
					WareOrderTaskDetailEntity entity = new WareOrderTaskDetailEntity(null, skuId, "", hasStock.getNum(), taskEntity.getId(), wareId, 1);
					wareOrderTaskDetailService.save(entity);
					StockLockedTo lockedTo = new StockLockedTo();
					lockedTo.setId(taskEntity.getId());
					StockDetailTo stockDetailTo = new StockDetailTo();
					BeanUtils.copyProperties(entity, stockDetailTo);
					lockedTo.setDetail(stockDetailTo);
					rabbitTemplate.convertAndSend("stock-event-exchange", "stock.locked", lockedTo);
					break;
				} else {
				}
			}
			if (skuStocked == false) {
				throw new NoStockExceptoin(skuId);
			}

		}
		return true;
	}

	@Override
	public void unLockStock(StockLockedTo to) {
		Long id = to.getId();// 库存工作单id；
		StockDetailTo detail = to.getDetail();
		Long detailId = detail.getId();
		// 解锁
		// 判断是否锁定失败。
		// 有 说明锁库成功，没有 说明锁库失败
		// 有 没有订单，需要解锁。有订单 看状态。
		// 订单 ： 取消了 要，
		// 现在这样式有问题的。
		WareOrderTaskDetailEntity byId = wareOrderTaskDetailService.getById(detailId);
		if (byId != null) {
			// 解锁
			WareOrderTaskEntity taskEntity = wareOrderTaskService.getById(id);
			String orderSn = taskEntity.getOrderSn();
			R r = orderFeignService.getOrderStatus(orderSn);
			if (r.getCode() == 0) {
				// 订单数据返回成功
				OrderVo data = r.getData(new TypeReference<OrderVo>() {
				});
				if (data == null || data.getStatus() == 4) {
					// 订单已经被取消
					if (byId.getLockStatus() == 1) {
						// 当前库存工作单状态，1.为锁定，锁定的才可以解锁
						unLockStock(detail.getSkuId(), detail.getWareId(), detail.getSkuNum(), detailId);
					}

				}
			} else {
				throw new RuntimeException("远程订单服务调用失败");
			}
		} else {
			// 无需解锁
		}
	}

	/**
	 * 防止订单服务卡顿，导致订单状态一直改不了
	 *
	 * @param orderTo
	 */
	@Override
	@Transactional
	public void unLockStock(OrderTo orderTo) {
		String orderSn = orderTo.getOrderSn();
		// 查询库存状态
		// R r = orderFeignService.getOrderStatus(orderSn); 能来到这的消息，就已经是关闭的了
		WareOrderTaskEntity wareOrderTaskEntity = wareOrderTaskService.getOrderTaskByOrderSn(orderSn);
		Long id = wareOrderTaskEntity.getId();
		List<WareOrderTaskDetailEntity> list = wareOrderTaskDetailService.list(
				new QueryWrapper<WareOrderTaskDetailEntity>()
						.eq("task_id", id)
						.eq("lock_status", 1));
		for (WareOrderTaskDetailEntity entity : list) {
			unLockStock(entity.getSkuId(), entity.getWareId(), entity.getSkuNum(), entity.getTaskId());
		}
	}

	/**
	 * 库存解锁方法
	 *
	 * @param SkuId
	 * @param wareId
	 * @param num
	 * @param taskDetailId
	 */
	private void unLockStock(Long SkuId, Long wareId, Integer num, Long taskDetailId) {
		// 库存解锁
		wareSkuDao.unlockStock(SkuId, wareId, num);
		// 更新库存工作单状态
		WareOrderTaskDetailEntity entity = new WareOrderTaskDetailEntity();
		entity.setId(taskDetailId);
		entity.setLockStatus(2);
		wareOrderTaskDetailService.updateById(entity);
	}

	@Data
	class SkuWareHasStock {
		private Long skuId;
		private List<Long> wareId;
		private Integer num;
	}

}




